﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO.Pipes;
using System.IO;

namespace ConsoleApplication
{
    class PipeServer
    {
        /// <summary>
        /// 匿名管道帮助在子进程和父进程之间提供安全可靠的进程间通信。 AnonymousPipeServerStream 类使父进程能够向子进程发送信息或接收来自子进程的信息。
        /// 匿名管道是未命名的单向管道，主要用于在父进程和子进程之间传输数据。 匿名管道始终是本地的；
        /// 它们不能通过网络使用。 由于匿名管道被定义为单向管道，因此不支持 InOut 的 PipeDirection 值。匿名管道不支持 Message 读取模式。
        /// 必须从管道句柄创建匿名管道客户端，该管道句柄由服务器端通过调用 GetClientHandleAsString 方法提供。 然后，在创建客户端进程时将该字符串作为参数传递。 
        /// 在客户端进程中，它又作为 pipeHandleAsString 参数被传递给 AnonymousPipeClientStream 构造函数。
        /// AnonymousPipeServerStream 对象必须使用 DisposeLocalCopyOfClientHandle 方法释放客户端句柄，以便在客户端退出时能够收到通知。
        /// </summary>
        static void Main()
        {
            Process pipeClient = new Process();
            pipeClient.StartInfo.FileName = "pipeClient.exe";

            using (AnonymousPipeServerStream pipeServer = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable))
            {
                // Show that anonymous pipes do not support Message mode.
                try
                {
                    Console.WriteLine("[SERVER] Setting ReadMode to \"Message\".");
                    pipeServer.ReadMode = PipeTransmissionMode.Message;
                }
                catch (NotSupportedException e)
                {
                    Console.WriteLine("[SERVER] Exception:\n    {0}", e.Message);
                }
                Console.WriteLine("[SERVER] Current TransmissionMode: {0}.",
                pipeServer.TransmissionMode);

                // Pass the client process a handle to the server.
                pipeClient.StartInfo.Arguments = pipeServer.GetClientHandleAsString();
                pipeClient.StartInfo.UseShellExecute = false;
                pipeClient.Start();

                pipeServer.DisposeLocalCopyOfClientHandle();

                try
                {
                    // Read user input and send that to the client process.
                    using (StreamWriter sw = new StreamWriter(pipeServer))
                    {
                        sw.AutoFlush = true;
                        // Send a 'sync message' and wait for client to receive it.
                        sw.WriteLine("SYNC");

                        pipeServer.WaitForPipeDrain();

                        // Send the console input to the client process.
                        Console.Write("[SERVER] Enter text: " + Environment.NewLine);
                        string userCode = string.Empty;
                        do
                        {
                            userCode = Console.ReadLine();
                            sw.WriteLine(userCode);
                        } while (userCode != "N");
                    }
                }
                // Catch the IOException that is raised if the pipe is broken
                // or disconnected.
                catch (IOException e)
                {
                    Console.WriteLine("[SERVER] Error: {0}", e.Message);
                }
            }
            pipeClient.WaitForExit();
            pipeClient.Close();


            Console.WriteLine("[SERVER] Client quit. Server terminating.");
            Console.ReadLine();
        }
    }
}
